
<template>
  <el-table v-if="cols" ref="ElTable" class="table-slot" :data="data" :default-sort="default_sort" border stripe :header-cell-style="{background: 'var(--color-bg)'}"
            @selection-change="select_change" @sort-change="sort_change" :row-class-name="row_class" :cell-class-name="cell_class">
    <template #default>
      <el-table-column v-if="has_select" type="selection" width="30" align="center" fixed="left"></el-table-column>
      <template v-for="col in cols">
        <el-table-column v-if="col.type !== 'hidden'" v-bind="bind_column(col)">
          <template #default="{row, $index}">
            <template v-if="col.type && $slots[col.type]">
              <slot :name="col.type" :row="row" :col="col" :index="$index"></slot>
            </template>
            <UnifyParam v-else :ref="(el)=>{ref_map[`${col.name}:${$index}`]=el}" :_type_="col.type" :model-value="row[col.name]" :_props_="bind_unify_param(row, col)" @change="onchange(row, col, $event, $index)"></UnifyParam>
          </template>
        </el-table-column>
      </template>
    </template>
  </el-table>
</template>
<script lang="ts">
import UnifyParam from "@/components/auto_import/UnifyParam.vue";
import type {TypeParamComponents} from '@/components/auto_import/UnifyParam.vue'
import type {PropType} from "vue";
// @ts-ignore
import {filter_object} from "@/js/s94_tool.js";

export interface TypeCol {
  label: string;
  name: string;
  order?: boolean;
  align?: string;
  width?: string | number;
  min_width?: string | number;
  fixed?: 'left' | 'right' | string;

  type?: TypeParamComponents | string,
  can_edit?: boolean,
  onchange?: (row:any, col:TypeCol, v:any, index:number)=>boolean|undefined;
}


export default {
  _title_: '表格',
  _tip_: '表格组件，对ElTable进行封装，cols每项的 type 属性定义参数类型或者插槽名（优先级更高），插槽接受参数：row、col、index',
  _css_var_: {},
  components: {
    UnifyParam
  },
  props: {
    data: {
      type: Array,
      default: [],
    },
    cols: {
      type: Object as PropType<{[key:string]: TypeCol}>,
      default: {},
    },
    default_order: {
      type: String,
      default: '',
    },
    has_select: Boolean,
    row_class: {
      type: [String, Function] as PropType<string | ((data: { row: any, rowIndex: number }) => string)>,
    },
    cell_class: {
      type: [String, Function]  as PropType<string | ((data: { row: any, column: any, rowIndex: number, columnIndex: number }) => string)>,
    },
  },
  emits: ['change:selected', 'change:order'],
  data(){
    let selected:any[] = [];
    let ref_map:{[p:string]: any} = [];
    let default_sort = {prop: '', order: ''};
    if (this.default_order){
      // @ts-ignore
      let arr = this.default_order.split(' ');
      default_sort.prop = arr[0];
      default_sort.order = ((arr[1] || 'asc')+'ending').toLowerCase();
    }
    return {
      selected,
      ref_map,
      default_sort,
    }
  },
  methods: {
    topx(v:any){
      v = v ? (v+'') : '';
      let str = v.replace(/([\d\.]+)rem/, '($1*rem)').
      replace(/(\d+)px/, '$1');
      return (new Function('rem','return '+str))(100);
    },
    bind_column(col:TypeCol){
      // 计算 el-table-column 组件属性绑定
      let res = {
        label: col.label,
        prop: col.name,
        align: col.align || 'center',
        sortable: col.order ? 'custom' : false,
        width: col.width ? this.topx(col.width) : undefined,
        'min-width': this.topx(col.min_width || '60'),
        fixed: col.fixed,
      };
      return res;
    },
    bind_unify_param(row:any, col:TypeCol){
      let column_keys = [
        'label',
        'name',
        'align',
        'order',
        'width',
        'min_width',
        'fixed',
      ];
      let res = filter_object(col, column_keys);
      res.is_list = true;
      res.is_info = !col.can_edit;
      return res;
    },
    async onchange(row:any, col:TypeCol, v:any, index:number){
      if (typeof(col.onchange) == 'function'){
        let res = await col.onchange(row, col, v, index);
        if (res === false) {
          // @ts-ignore
          let ref = this.ref_map[`${col.name}:${index}`];
          if (typeof ref?.set_value === 'function') ref?.set_value(row[col.name])
          return;
        }
      }
      row[col.name] = v;
    },
    select_change(selected:any[]){
      // @ts-ignore
      this.selected = selected;
      // @ts-ignore
      this.$emit('change:selected', this.selected);
    },
    // @ts-ignore
    sort_change({column, prop, order}){
      const order_sql = prop && order ? `${prop} ${order.replace('ending','')}` : '';
      // @ts-ignore
      this.$emit('change:order', order_sql);
    },
  },
  watch: {
    data(v:any, oldV:any){
      // 数据变化后，清空选择
      // @ts-ignore
      this.select_change([]);
    },
  },
  computed: {

  },
  mounted() {
  },
}

</script>

<style scoped>
.table-slot{width: 100%;}
</style>